package fi.iki.juri.units.generator;

import java.io.StringWriter;
import java.util.Collection;

import fi.iki.juri.units.generator.ParsedTranslations.Translation;

public class PythonGenerator implements CodeGenerator {
	private final String outputName;

	public PythonGenerator(final String outputName) {
		this.outputName = outputName;
	}
	
	public String generate(Collection<ParsedUnit> units,
			Collection<ParsedTranslations> translations) {
		final StringWriter pWriter = new StringWriter();
		writeModuleHead(pWriter);
		final StringBuilder createUnits = new StringBuilder(1024);
		final StringBuilder deriveUnits = new StringBuilder(1024);
		for (final ParsedUnit unit : units) {
			createUnits.append(String.format("\tcreate_unit(map, u\"%s\")\n", unit.getId()));
			for (final String alias : unit.getAliases()) {
				createUnits.append(String.format("\talias_unit(map, u\"%s\", u\"%s\")\n", unit.getId(), alias));
			}
			if (unit.getDerive() != null) {
				deriveUnits.append(String.format("\tmap[u\"%s\"].derive_unit(map[u\"%s\"], ",
						unit.getId(), unit.getDerive()));
				
				final String fromExpr = unit.getFromFormula() != null ? unit.getFromFormula() : (unit.getToFormula() != null ? GeneratorTools.reverseExpression(unit.getToFormula()) : "");
				final String toExpr = unit.getToFormula() != null ? unit.getToFormula() : (unit.getFromFormula() != null ? GeneratorTools.reverseExpression(unit.getFromFormula()) : "");
				deriveUnits.append(String.format("lambda x: %s, ", GeneratorTools.postfix2infix("x " + fromExpr, "x")));
				deriveUnits.append(String.format("lambda x: %s", GeneratorTools.postfix2infix("x " + toExpr, "x")));
				deriveUnits.append(")\n");
			}
		}
		pWriter.write(createUnits.toString());
		pWriter.write(deriveUnits.toString());
		pWriter.write("\treturn map\n\n");
		pWriter.write("def get_translations(units):\n");
		pWriter.write("\ttranslations = {}\n");
		for (final ParsedTranslations trans : translations) {
			pWriter.write("\ttrans = {}\n");
			pWriter.write(String.format("\ttranslations[u\"%s\"] = trans\n", trans.getLocale()));
			for (final Translation t : trans.getTranslations()) {
				pWriter.write(String.format("\ttrans[u\"%s\"] = units[u\"%s\"]\n", t.getTranslation(), t.getUnit()));
			}
		}
		pWriter.write("\treturn translations\n");
		return pWriter.toString();
	}

	private void writeModuleHead(final StringWriter writer) {
		final String head = "# coding=utf-8\n\n" +
			"from unit import Unit\n\n" +
			"def create_unit(map, name):\n" +
			"\tmap[name] = Unit(name)\n\n" +
			"def alias_unit(map, original, alias):\n" +
			"\tmap[alias] = map[original]\n\n" +
			"def create_units_map():\n" +
			"\tmap = {}\n";
		writer.write(head);
	}

	public String outputName() {
		return outputName + ".py";
	}
}
